package net.seabookchen.service;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import net.seabookchen.dao.LinkedInDao;
import net.seabookchen.pojo.LinkedInResume;
import net.seabookchen.pojo.linkedin.Company;
import net.seabookchen.pojo.linkedin.LinkedInEducation;
import net.seabookchen.pojo.linkedin.LinkedInPerson;
import net.seabookchen.pojo.linkedin.LinkedInPosition;
import net.seabookchen.util.DateUtils;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.scribe.builder.ServiceBuilder;
import org.scribe.builder.api.LinkedInApi;
import org.scribe.model.OAuthRequest;
import org.scribe.model.Response;
import org.scribe.model.Token;
import org.scribe.model.Verb;
import org.scribe.oauth.OAuthService;

import com.google.appengine.api.datastore.EntityNotFoundException;

public class LinkedInResumeService {
	private static final Logger log = Logger
			.getLogger(LinkedInResumeService.class.getName());

	private static final String API_KEY = "jEybmOXZoKtTCQIl025e1hLLRH9PCYPP4MUZoYSlnHqiXlWL5kJrTVzjo6Y32H3v";
	private static final String API_KEY_SECRECT = "7hbSNbPCQ2Imo3aInDbb6BrtsZkIByN6MepL7eODMquEPLULKZFkORWoTaLjKu7F";

	private static final String ACCESS_TOKEN = "90e4476d-7cba-4c9f-873b-db98469f01bd";
	private static final String ACCESS_SECRET = "b930edda-8eec-4490-bfc9-f4e8ef1dc1e3";

	private static final String PROTECTED_RESOURCE_URL = "http://api.linkedin.com/v1/people/url=http%3A%2F%2Fau.linkedin.com%2Fpub%2Fseabook-chen%2F20%2F13%2F495:public";

	private LinkedInDao linkedInDao = new LinkedInDao(LinkedInResume.class);
	
	// we need to have a common key here
	private static long resumeKey = 123456789;

	public void buildResumeFromLinkedIn() {
		OAuthService service = new ServiceBuilder().provider(LinkedInApi.class)
				.apiKey(API_KEY).apiSecret(API_KEY_SECRECT).build();
		Token accessToken = new Token(ACCESS_TOKEN, ACCESS_SECRET);
		OAuthRequest request = new OAuthRequest(Verb.GET,
				PROTECTED_RESOURCE_URL);
		service.signRequest(accessToken, request);
		Response response = null;
		response = request.send();
		log.info("Retrieve Request Successfully.");
		String storedXMLProfile = response.getBody();
		if (storedXMLProfile == null || storedXMLProfile.length() == 0) {
			throw new RuntimeException(
					"Build LinkedInPerson Profile Falied due to no Stored XML Profile");
		}
		
		// save or update the Resume
		LinkedInResume inResume = null;
		try {
			inResume = linkedInDao.get(resumeKey);
			inResume.setLinkedInXml(storedXMLProfile);
		} catch (Exception e) {
			inResume = new LinkedInResume(storedXMLProfile);
			inResume.setId(resumeKey);
		}
		linkedInDao.put(inResume);
	}

	public LinkedInPerson getLinkedInProfile() {
		LinkedInResume inResume = null;
		try {
			inResume = linkedInDao.get(resumeKey);
		} catch (Exception e) {
			return null;
		}

		InputStream inputStream = null;
		Document document = null;
		SAXReader reader = new SAXReader();
		try {
			inputStream = new ByteArrayInputStream(inResume.getLinkedInXml().getBytes());
			document = reader.read(inputStream);
		} catch (DocumentException e) {
			log.severe(e.getMessage());
			throw new RuntimeException("Wrong LinkedIn URL!");
		}

		LinkedInPerson person = new LinkedInPerson();

		String firstname = document.selectSingleNode("//person/first-name")
				.getText();
		String lastname = document.selectSingleNode("//person/last-name")
				.getText();
		String location = document.selectSingleNode("//person/location/name")
				.getText();
		String headline = document.selectSingleNode("//person/headline")
				.getText();
		String summary = document.selectSingleNode("//person/summary")
				.getText();
		String industry = document.selectSingleNode("//person/industry")
				.getText();

		person.setFirstname(firstname);
		person.setLastname(lastname);
		person.setHeadline(headline);
		person.setSummary(summary);
		person.setLocation(location);
		person.setIndustry(industry);

		// Dealing with positions
		List<LinkedInPosition> positions = new ArrayList<LinkedInPosition>();
		List<Element> list = document
				.selectNodes("//person/positions/position");
		for (int i = 0; i < list.size(); i++) {
			LinkedInPosition position = new LinkedInPosition();

			Element element = list.get(i);

			Node title = element.selectSingleNode("title");
			position.setTitle(validNodeStringValue(title));

			Node nSummary = element.selectSingleNode("summary");
			position.setSummary(validNodeStringValue(nSummary));

			Node startDateYear = element.selectSingleNode("start-date/year");
			Node startDateMonth = element.selectSingleNode("start-date/month");
			String startDateStr = processDate(startDateYear, startDateMonth);
			position.setStartDate(startDateStr);

			Node endDateYear = element.selectSingleNode("end-date/year");
			Node endDateMonth = element.selectSingleNode("end-date/month");
			String endDateStr = processDate(endDateYear, endDateMonth);
			position.setEndDate(endDateStr);

			Node isCurrent = element.selectSingleNode("is-current");
			position.setCurrent(Boolean
					.parseBoolean(validNodeStringValue(isCurrent)));

			Company company = new Company();
			Node comapnyName = element.selectSingleNode("company/name");
			company.setName(validNodeStringValue(comapnyName));

			Node comapnyType = element.selectSingleNode("company/type");
			company.setType(validNodeStringValue(comapnyType));

			Node comapnyIndustryType = element
					.selectSingleNode("company/industry");
			company.setIndustry(validNodeStringValue(comapnyIndustryType));

			position.setCompany(company);

			positions.add(position);
		}

		person.setPositions(positions);

		// Dealing with educations
		List<LinkedInEducation> educationsList = new ArrayList<LinkedInEducation>();
		List<Element> educations = document
				.selectNodes("//person/educations/education");
		for (Element element : educations) {
			LinkedInEducation education = new LinkedInEducation();

			Node schoolName = element.selectSingleNode("school-name");
			education.setSchoolName(validNodeStringValue(schoolName));

			Node startYear = element.selectSingleNode("start-date/year");
			Node endYear = element.selectSingleNode("end-date/year");

			education.setStartDate(validNodeStringValue(startYear));
			education.setEndDate(validNodeStringValue(endYear));

			educationsList.add(education);
		}

		person.setEducations(educationsList);

		return person;
	}

	private String processDate(Node yearNode, Node monthNode) {
		String year = null;
		String month = null;

		if (yearNode == null && monthNode == null) {
			return "Present";
		}

		if (yearNode != null) {
			year = yearNode.getText();
		}

		if (monthNode != null) {
			month = DateUtils
					.getMonthDesc(Integer.valueOf(monthNode.getText()));
		}

		return month + " " + year;
	}

	private String validNodeStringValue(Node node) {
		if (node != null) {
			return node.getText();
		}
		return null;
	}
}
